import { Router } from 'express';
import { Op } from 'sequelize';
import {
	User,
	Balance,
	PayType,
	Ticker,
	Exchange,
	Currency,
	OrderStatus,
} from '../models_nosql';
import { MerchantOrder_SQL, SpotOrder_SQL } from '../models_sql';
import {
	checkOrderInDB,
	getArraySortedByProp,
	// getTickerPriceUSDT,
	getPriceTicker,
	getArrayItemsCustomed,
	startHandlerAllOtcOrders,
	startHandlerAllSpotOrders,
	getAllBalances,getSingleUserProperty
} from '../common';
import { TEXT_CONSTANTS } from '../constants';

export const reportsRouter = Router();

// получение данных из БД
reportsRouter.post('/data-by-date', async (req, res) => {
	// console.log(req.body);
	const {
		userId,
		startTime,
		endTime,
		exchangeId,
		payTypeId,
		coin,
		fiat,
		subAccount,
		sideType,
		orderType,
		isMonthStats,
		isYearStatsV1,
		isYearStatsV2,
		isYearStatsV3,
		isCostReport,
	} = req.body;

	const queryMerchantOrders = {
		where: {
			// userId,
			userId:
				userId === ''
					? {
							[Op.or]: [
								'6086427c72453019ec72dbb3',
								'60d99fdbd9d1a913a84e3011',
							],
					  }
					: userId,
			exchangeId:
				exchangeId !== '' ? { [Op.eq]: exchangeId } : { [Op.not]: null },
			payMethodId:
				payTypeId !== '' ? { [Op.eq]: payTypeId } : { [Op.not]: null },
			payMerchantAccount:
				subAccount === ''
					? { [Op.not]: null }
					: subAccount === 'xxx'
					? { [Op.eq]: '' }
					: { [Op.eq]: subAccount },
			tradeType:
				sideType !== '' ? { [Op.eq]: sideType } : { [Op.not]: null },
			asset: coin !== '' ? { [Op.eq]: coin } : { [Op.not]: null },
			fiat: fiat !== '' ? { [Op.eq]: fiat } : { [Op.not]: null },
			dateOrder: {
				// dateOrder >= startTime && createTime =< endTime
				[Op.lt]: endTime,
				[Op.gt]: startTime,
			},
		},
	};
	const querySpotOrders = {
		where: {
			// userId,
			userId:
				userId === ''
					? {
							[Op.or]: [
								'6086427c72453019ec72dbb3',
								'60d99fdbd9d1a913a84e3011',
							],
					  }
					: userId,
			exchangeId:
				exchangeId !== '' ? { [Op.eq]: exchangeId } : { [Op.not]: null },
			sideType:
				sideType !== '' ? { [Op.eq]: sideType } : { [Op.not]: null },
			baseAsset: coin !== '' ? { [Op.eq]: coin } : { [Op.not]: null },
			dateOrder: {
				[Op.lt]: endTime,
				[Op.gt]: startTime,
			},
		},
	};
	const queryBalances = {
		userId: userId,
		createdAt: {
			$gte: startTime,
			$lte: endTime,
		},
	};
	const merchantOrders = await MerchantOrder_SQL.findAll(
		queryMerchantOrders
	);
	const spotOrders = await SpotOrder_SQL.findAll(querySpotOrders);
	const reportBalances = await Balance.find(queryBalances);

	const months = [
		'1',
		'2',
		'3',
		'4',
		'5',
		'6',
		'7',
		'8',
		'9',
		'10',
		'11',
		'12',
	];
	const message = `DB result:
		${spotOrders.length} spotOrders 
		${merchantOrders.length} merchantOrders`;

	const arrTickers = await Ticker.find();
	const arrCurrencies = await Currency.find();
	const arrPayTypes = await PayType.find();
	const arrExchanges = getArraySortedByProp(
		'ALL',
		await Exchange.find(),
		'createdAt'
	);

	// Получение массива статистики за месяц по биржам
	const getMonthStats = async (tradeType) => {
		const queryMonthOtcOrders = {
			where: {
				// userId,
				userId:
					userId === ''
						? {
								[Op.or]: [
									'6086427c72453019ec72dbb3',
									'60d99fdbd9d1a913a84e3011',
								],
						  }
						: userId,
				fiat: fiat !== '' ? { [Op.eq]: fiat } : { [Op.not]: null },
				dateOrder: {
					// dateOrder >= startTime && createTime =< endTime
					[Op.lt]: endTime,
					[Op.gt]: startTime,
				},
			},
		};
		const monthStatOtcOrders = await MerchantOrder_SQL.findAll(
			queryMonthOtcOrders
		);
		const coinsArray = arrCurrencies.filter((item) => {
			return item.currencyType === 'coin';
		});
		const result = [];
		for (let i = 0; i < coinsArray.length; i++) {
			const obj = {
				currency: coinsArray[i].currency,
				tradeSide: tradeType,
				props: [],
			};
			for (let j = 0; j < arrExchanges.length; j++) {
				const ordersFiltered = monthStatOtcOrders.filter((item) => {
					return (
						item.exchangeId === arrExchanges[j]._id.toString() &&
						item.asset === coinsArray[i].currency &&
						item.tradeType === tradeType
					);
				});
				let orderSumm = 0;
				let tradeCount = 0;
				const propsObj = { exchange: arrExchanges[j].shortName };
				if (ordersFiltered.length !== 0) {
					for (let k = 0; k < ordersFiltered.length; k++) {
						orderSumm += +ordersFiltered[k].amount;
						tradeCount++;

						propsObj.orderSumm = orderSumm.toFixed(0);
						propsObj.tradeCount = tradeCount;
					}
				}
				if (orderSumm !== 0) obj.props.push(propsObj);
			}
			if (obj.props.length !== 0) result.push(obj);
		}
		return result;
	};

	// Получение наименования месяца EN
	const getMonthNameByDate = (date) => {
		const nameMonth = new Date(date).toLocaleDateString('En', {
			month: 'short',
		});
		return nameMonth;
	};

	const nowYear = new Date(startTime).getFullYear();
	const firstYearDate = new Date(`${nowYear}-01-01`);
	const lastYearDate = new Date(`${+nowYear + 1}-01-01`);
	const queryYearOtcOrders = {
		where: {
			// userId,
			userId:
				userId === ''
					? {
							[Op.or]: [
								'6086427c72453019ec72dbb3',
								'60d99fdbd9d1a913a84e3011',
							],
					  }
					: userId,
			fiat: fiat !== '' ? { [Op.eq]: fiat } : { [Op.not]: null },
			dateOrder: {
				// dateOrder >= startTime && createTime =< endTime
				[Op.lt]: lastYearDate,
				[Op.gt]: firstYearDate,
			},
		},
	};
	const yearStatOtcOrders = await MerchantOrder_SQL.findAll(
		queryYearOtcOrders
	);

	// by assets Получение массива статистики за год по месячно
	const getYearStatsV1 = async (tradeType) => {
		const coinsArray = arrCurrencies.filter((item) => {
			return item.currencyType === 'coin';
		});
		const result = [];
		for (let i = 0; i < coinsArray.length; i++) {
			const obj = {
				currency: coinsArray[i].currency,
				tradeSide: tradeType,
				props: [],
			};
			for (let j = 0; j < months.length; j++) {
				const monthName = getMonthNameByDate(months[j]);
				const ordersFiltered = yearStatOtcOrders.filter((item) => {
					return (
						monthName === getMonthNameByDate(item.dateOrder) &&
						item.asset === coinsArray[i].currency &&
						item.tradeType === tradeType
					);
				});
				let orderSumm = 0;
				let tradeCount = 0;
				const propsObj = { month: monthName };
				if (ordersFiltered.length !== 0) {
					for (let k = 0; k < ordersFiltered.length; k++) {
						orderSumm += +ordersFiltered[k].amount;
						tradeCount++;

						propsObj.orderSumm = orderSumm.toFixed(0);
						propsObj.tradeCount = tradeCount;
					}
				}
				if (orderSumm !== 0) obj.props.push(propsObj);
			}
			if (obj.props.length !== 0) result.push(obj);
		}
		return result;
	};

	// by exchanges Получение массива статистики за год по месячно
	const getYearStatsV2 = async (tradeType) => {
		const activeExchanges = arrExchanges.filter((item) => {
			// return item.status;
			return item.shortName;
		});
		const result = [];
		for (let i = 0; i < activeExchanges.length; i++) {
			const obj = {
				exchange: activeExchanges[i].shortName,
				tradeSide: tradeType,
				props: [],
			};
			for (let j = 0; j < months.length; j++) {
				const monthName = getMonthNameByDate(months[j]);
				const ordersFiltered = yearStatOtcOrders.filter((item) => {
					return (
						monthName === getMonthNameByDate(item.dateOrder) &&
						// item.exchange === activeExchanges[i].shortName &&
						item.exchangeId === activeExchanges[i]._id.toString() &&
						item.tradeType === tradeType
					);
				});
				let orderSumm = 0;
				let tradeCount = 0;
				const propsObj = { month: monthName };
				if (ordersFiltered.length !== 0) {
					for (let k = 0; k < ordersFiltered.length; k++) {
						orderSumm += +ordersFiltered[k].amount;
						tradeCount++;

						propsObj.orderSumm = orderSumm.toFixed(0);
						propsObj.tradeCount = tradeCount;
					}
				}
				if (orderSumm !== 0) obj.props.push(propsObj);
			}
			if (obj.props.length !== 0) result.push(obj);
		}
		return result;
	};

	// by payMethods Получение массива статистики за год по месячно
	const getYearStatsV3 = async (tradeType) => {
		const result = [];
		for (let i = 0; i < arrPayTypes.length; i++) {
			const obj = {
				payType: arrPayTypes[i].payType,
				payMethodId: arrPayTypes[i]._id.toString(),
				tradeSide: tradeType,
				props: [],
			};
			for (let j = 0; j < months.length; j++) {
				const monthName = getMonthNameByDate(months[j]);
				const ordersFiltered = yearStatOtcOrders.filter((item) => {
					return (
						monthName === getMonthNameByDate(item.dateOrder) &&
						item.payMethodId === obj.payMethodId &&
						item.tradeType === tradeType
					);
				});
				let orderSumm = 0;
				let tradeCount = 0;
				const propsObj = { month: monthName };
				if (ordersFiltered.length !== 0) {
					for (let k = 0; k < ordersFiltered.length; k++) {
						orderSumm += +ordersFiltered[k].amount;
						tradeCount++;

						propsObj.orderSumm = orderSumm.toFixed(0);
						propsObj.tradeCount = tradeCount;
					}
				}
				if (orderSumm !== 0) obj.props.push(propsObj);
			}
			if (obj.props.length !== 0) result.push(obj);
		}
		return result;
	};

	// обновление costReport
	const updateCostReport = (params) => {
		const { typeOrder, asset, fiat, tradeType } = params;
		let totalAmount = 0;
		let totalVolume = 0;
		let deals = 0;
		let result = { typeOrder, fiat, tradeType };
		if (typeOrder === 'P2P') {
			merchantOrders.forEach((i) => {
				if (
					i.asset === asset &&
					i.fiat === fiat &&
					i.tradeType === tradeType
				) {
					totalAmount += +i.amount;
					totalVolume += +i.volume;
					deals++;
				}
			});
		} else if (typeOrder === 'SPOT') {
			spotOrders.forEach((i) => {
				if (
					i.baseAsset === asset &&
					i.quoteAsset === fiat &&
					i.sideType === tradeType
				) {
					totalAmount += +(i.price * i.volume);
					totalVolume += +i.volume;
					deals++;
				}
			});
		}
		return {
			...result,
			totalAmount,
			totalVolume,
			deals,
			course: totalAmount === 0 ? 0 : totalAmount / totalVolume,
		};
	};

	// расчет cost на начало периода
	const getStartCost = (asset) => {
		const result = reportBalances[0].cost.filter((k) => {
			return k.asset === asset;
		});
		return {
			courseAsset: result.length === 0 ? 0 : +result[0].courseAsset,
			courseUSDT: result.length === 0 ? 0 : +result[0].courseUSDT,
		};
	};

	// расчет costReport
	const getCostReport = () => {
		// получаем массив уникальных значений нименований крипты
		const listAssets = [
			{ asset: 'USDT' },
			{ asset: 'BTC' },
			{ asset: 'ETH' },
			{ asset: 'RUB' },
			{ asset: 'USDC' },
			{ asset: 'TON' },
			{ asset: 'XMR' },
			{ asset: 'LTC' },
			// { asset: "HT" },
			{ asset: 'USDD' },
			{ asset: 'KAS' },
		];

		for (let i = 0; i < listAssets.length; i++) {
			if (reportBalances.length !== 0) {
				let summ = 0;
				let volume = 0;
				reportBalances[reportBalances.length - 1].balances.forEach((k) => {
					if (k.asset === listAssets[i].asset) {
						summ += +k.summ;
						volume += +k.volume;
					}
				});
				listAssets[i].startBalance = {
					summUSDT: summ,
					volumeAsset: volume,
					cost:
						!reportBalances[0].cost || reportBalances[0].cost.length === 0
							? { courseAsset: 0, courseUSDT: 0 }
							: getStartCost(listAssets[i].asset),
				};
			}
			if (merchantOrders.length !== 0) {
				const asset = listAssets[i].asset;
				const trades = [
					updateCostReport({
						typeOrder: 'P2P',
						asset,
						fiat: 'RUB',
						tradeType: 'BUY',
					}),
					updateCostReport({
						typeOrder: 'P2P',
						asset,
						fiat: 'RUB',
						tradeType: 'SELL',
					}),
					updateCostReport({
						typeOrder: 'P2P',
						asset,
						fiat: 'USD',
						tradeType: 'BUY',
					}),
					updateCostReport({
						typeOrder: 'P2P',
						asset,
						fiat: 'USD',
						tradeType: 'SELL',
					}),
					updateCostReport({
						typeOrder: 'P2P',
						asset,
						fiat: 'EUR',
						tradeType: 'BUY',
					}),
					updateCostReport({
						typeOrder: 'P2P',
						asset,
						fiat: 'EUR',
						tradeType: 'SELL',
					}),
					updateCostReport({
						typeOrder: 'SPOT',
						asset,
						fiat: 'RUB',
						tradeType: 'BUY',
					}),
					updateCostReport({
						typeOrder: 'SPOT',
						asset,
						fiat: 'RUB',
						tradeType: 'SELL',
					}),
					updateCostReport({
						typeOrder: 'SPOT',
						asset,
						fiat: 'USDT',
						tradeType: 'BUY',
					}),
					updateCostReport({
						typeOrder: 'SPOT',
						asset,
						fiat: 'USDT',
						tradeType: 'SELL',
					}),
				];
				listAssets[i].trades = trades;
			}
		}

		// console.log(listAssets[1], listAssets[2]);
		return listAssets;
	};

	// обновление баланса
	const updateBalance = async () => {
		const params = {
			isUpdate: !true,
			localDate: '01.07.2022',
			cost: [
				{
					asset: 'USDT',
					courseAsset: '58.67', // расчетный закуп RUB
					courseUSDT: '1',
				},
				{
					asset: 'BTC',
					courseAsset: '1288236.67', // расчетный закуп RUB
					courseUSDT: '22800',
				},
				{
					asset: 'ETH',
					courseAsset: '53647.11', // расчетный закуп RUB
					courseUSDT: '80795.83',
				},
			],
		};

		if (params.isUpdate) {
			// поиск balance в БД
			const qwery = {
				userId,
				localDate: params.localDate,
			};
			const balance = await Balance.findOne(qwery);

			// если balance не уникальный и нашелся в БД
			if (balance) {
				balance.cost = params.cost;
				// console.log(balance);
				balance
					.save({ raw: true })
					.then(() => {
						const message = `****${userId.slice(
							-4
						)} | This Balance updated!`;
						console.log(message);
					})
					.catch((error) => {
						console.log(error);
					});
			}
		}
	};

	// await updateBalance();

	return res.status(200).send({
		reportSpotOrders:
			orderType === 'ALL' || orderType === 'SPOT'
				? getArraySortedByProp('ALL', spotOrders, 'dateOrder')
				: [],
		reportMerchantOrders:
			orderType === 'ALL' || orderType === 'OTC'
				? getArraySortedByProp('ALL', merchantOrders, 'dateOrder')
				: [],
		reportBalances,
		reportCost: isCostReport ? getCostReport() : [],
		reportStats: {
			monthStats: isMonthStats
				? {
						sell: await getMonthStats('SELL'),
						buy: await getMonthStats('BUY'),
				  }
				: { sell: [], buy: [] },
			yearStatsV1: isYearStatsV1
				? {
						sell: await getYearStatsV1('SELL'),
						buy: await getYearStatsV1('BUY'),
				  }
				: { sell: [], buy: [] },
			yearStatsV2: isYearStatsV2
				? {
						sell: await getYearStatsV2('SELL'),
						buy: await getYearStatsV2('BUY'),
				  }
				: { sell: [], buy: [] },
			yearStatsV3: isYearStatsV3
				? {
						sell: await getYearStatsV3('SELL'),
						buy: await getYearStatsV3('BUY'),
				  }
				: { sell: [], buy: [] },
		},
		tickers: arrTickers,
		message,
		success: true,
	});
});

// получение данных о неоплаченных ордерах из БД
reportsRouter.post('/check-status', async (req, res) => {
	const user = await User.findOne({ _id: req.body.userId });
	let countUnpaid = 0;
	const orderStatuses = user.properties.map((item, index) => {
		if (item.orderStatuses.unpaid > 0) countUnpaid++;
		return {
			unpaid: item.orderStatuses.unpaid,
			paid: item.orderStatuses.paid,
			exchange: item.exchange,
		};
	});

	return res.status(200).json({
		success: true,
		userOrderStatuses: orderStatuses,
		unpaidOrders: countUnpaid,
		// tickers: await Ticker.find(),
		message: `There is ${countUnpaid} unpaid orders`,
	});
});

// получение orderDetails из БД
reportsRouter.post('/edit-order', async (req, res) => {
	const { userId, orderId, exchange } = req.body;

	let order = {};
	let success = true;
	let message = `${exchange}: Order ****${orderId.slice(-4)} found`;

	// проверка наличия ордера в БД
	const result = await checkOrderInDB(
		userId,
		'MERCHANT',
		orderId,
		exchange
	);
	// если ордера нет в БД
	if (result.isUnique) {
		message = `${exchange}: Order ****${orderId.slice(
			-4
		)} isn't exists in DB`;
		success = false;
		// console.log(message)
	}
	// если ордер нашелся в БД
	else order = result.order;

	return res.status(200).send({
		success,
		message,
		orderDetails: order,
	});
});

// обновление ордера
reportsRouter.post('/update-order', async (req, res) => {
	let status = false;
	let message;
	const arrPayTypes = await PayType.find(); // типы оплаты из Бу
	const arrExchanges = await Exchange.find();

	// Получение названия платежного метода по его ID
	const getPayMethodNameById = (payId) => {
		let payMethodName = '';
		for (let i = 0; i < arrPayTypes.length; i++) {
			if (arrPayTypes[i]._id.toString() === payId)
				payMethodName = arrPayTypes[i].payType;
		}
		// console.log(payId, payMethodName);
		return payMethodName;
	};

	const {
		userId,
		orderId,
		exchangeId,
		exchange,
		tradeType,
		payMethodId,
		payMerchantAccount,
	} = req.body.itemDetails;

	// поиск ордера в БД
	const queryDB = { where: { userId, orderId, exchangeId } };
	const order = await MerchantOrder_SQL.findOne(queryDB);

	// если ордера нет в БД
	if (!order) {
		message = `${exchange}: Order ****${orderId.slice(
			-4
		)} isn't exists in DB`;
		return res.status(200).send({
			success: status,
			message,
		});
	}
	// если ордер нашелся в БД
	else {
		order.payMethodId = payMethodId;
		order.payMethodName = getPayMethodNameById(payMethodId);
		order.payMerchantAccount = payMerchantAccount;
		order.tradeType = tradeType;

		order
			.save({ raw: true })
			.then(() => {
				message = `${exchange}: Order ****${orderId.slice(-4)} updated!`;
				status = true;
				return res.status(200).json({
					success: status,
					message,
					itemFlag: req.body.itemFlag,
					itemDetails: {
						...req.body.itemDetails,
						payMethodName: order.payMethodName,
						payMethodId: order.payMethodId,
						payMerchantAccount: order.payMerchantAccount,
					},
				});
			})
			.catch((error) => {
				message = `${exchange}: Order ****${orderId.slice(
					-4
				)} isn't updated!`;
				console.log(error);
				return res.status(400).json({
					success: status,
					message,
				});
			});
	}
});

// обновление платежного метода => payType
reportsRouter.post('/update-paytype', async (req, res) => {
	let success = true;
	let message = '';
	const { payTypeId } = req.body.itemDetails;

	const itemPayType = await PayType.findOne({ _id: payTypeId });

	if (!itemPayType) {
		success = false;
		message = `PayType id: ****${payTypeId.slice(-8)} isn't exists in DB`;
	} else {
		itemPayType.payType = req.body.itemDetails.payType;
		itemPayType.iconUrlColor = req.body.itemDetails.iconUrlColor;
		itemPayType.payTypeProps = req.body.itemDetails.payTypeProps;

		await itemPayType
			.save()
			.then(() => {
				message = `${itemPayType.payType} updated!`;
				success = true;
			})
			.catch((error) => {
				message = `PayType id: ****${payTypeId.slice(-8)} isn't updated!`;
				console.log(error);
			});
	}

	const arrPayTypes = await PayType.find();

	return res.status(200).json({
		success,
		message,
		itemFlag: req.body.itemFlag,
		payTypes: getArrayItemsCustomed(arrPayTypes, 'arrPayTypes'),
	});
});

// обновление данных P2P-сервиса
reportsRouter.post('/update-exchange', async (req, res) => {
	let success = true;
	let message = '';
	const { id } = req.body.itemDetails;

	const exchange = await Exchange.findOne({ _id: id });
	const handlerExchangeUserDetails = async (exchange) => {
		const users = await User.find();
		for (let i = 0; i < users.length; i++) {
			const userProperties = users[i].properties.slice();
			const filteredProperties = userProperties.filter((item) => {
				return item.exchangeId === exchange._id.toString();
			});
			// если биржи нет в userProperties, то добавляем
			if (filteredProperties.length === 0) {
				const newItem = {
					exchange: exchange.name,
					exchangeId: exchange._id,
					exchangeUserId: '',
					userNickName: 'User',
					updateOrders: false,
					orderStatuses: { unpaid: 0, paid: 0 },
					soundAlert: 'Sound/newOrder.wav',
					payTypeList: [],
					requestHeader: {},
					apiKeys: {
						publicKey: '',
						secretKey: '',
						dateApiKeys: 0,
					},
					favorites: [],
				};
				userProperties.push(newItem);
			}
			// если биржа есть, то обновляем
			else {
				for (let j = 0; j < userProperties.length; j++) {
					if (userProperties[j].exchangeId === exchange._id.toString())
						userProperties[j].exchange = exchange.name;
				}
			}

			const user = await User.findOne({ _id: users[i]._id });
			const msg = `User ${users[i].login}`;
			if (!user) {
				console.log(msg + ` isn't exists in DB`);
			} else {
				user.properties = userProperties;
				await user
					.save()
					.then(() => {
						console.log(msg + ` updated!`);
					})
					.catch((error) => {
						console.log(msg + ` isn't updated!`);
						console.log(error);
					});
			}
		}
	};

	if (!exchange) {
		success = false;
		message = `Exchange id: ****${id.slice(-8)} isn't exists in DB`;
	} else {
		exchange.name = req.body.itemDetails.name;
		exchange.shortName = req.body.itemDetails.shortName;
		exchange.logo = req.body.itemDetails.logo;
		exchange.bg = req.body.itemDetails.bg;
		exchange.merchantDetail = req.body.itemDetails.merchantDetail;
		exchange.orderDetail = req.body.itemDetails.orderDetail;
		exchange.advDetail = req.body.itemDetails.advDetail;
		exchange.spotTrade = req.body.itemDetails.spotTrade;
		exchange.status = req.body.itemDetails.status;

		await exchange
			.save()
			.then(() => {
				message = `${exchange.name} updated!`;
				success = true;
				// изменение и сохранение userProperties
				handlerExchangeUserDetails(exchange);
			})
			.catch((error) => {
				message = `Exchange id: ****${id.slice(-8)} isn't updated!`;
				console.log(error);
			});
	}

	const arrExchanges = await Exchange.find();

	return res.status(200).json({
		success,
		message,
		itemFlag: req.body.itemFlag,
		exchanges: getArrayItemsCustomed(arrExchanges, 'arrExchanges'),
		// itemDetails: req.body.itemDetails,
	});
});

// обновление данных криптовалюты / фиата
reportsRouter.post('/update-currency', async (req, res) => {
	let success = true;
	let message = '';
	const { currencyId } = req.body.itemDetails;

	const itemCurrency = await Currency.findOne({ _id: currencyId });

	if (!itemCurrency) {
		success = false;
		message = `Currency id: ****${id.slice(-8)} isn't exists in DB`;
	} else {
		itemCurrency.currency = req.body.itemDetails.currency;
		itemCurrency.currencyName = req.body.itemDetails.currencyName;
		itemCurrency.currencyType = req.body.itemDetails.currencyType;
		itemCurrency.symbol = req.body.itemDetails.symbol;
		itemCurrency.iconUrl = req.body.itemDetails.iconUrl;
		itemCurrency.tickerUSDT = req.body.itemDetails.tickerUSDT;
		itemCurrency.currencyProps = req.body.itemDetails.currencyProps;

		await itemCurrency
			.save()
			.then(() => {
				message = `${itemCurrency.currency} updated!`;
				success = true;
			})
			.catch((error) => {
				message = `Currency id: ****${id.slice(-8)} isn't updated!`;
				console.log(error);
			});
	}

	const arrCurrencies = await Currency.find();

	return res.status(200).json({
		success,
		message,
		itemFlag: req.body.itemFlag,
		currencies: getArrayItemsCustomed(arrCurrencies, 'arrCurrencies'),
	});
});

// обновление данных orderStatus ордеров
reportsRouter.post('/update-status', async (req, res) => {
	let success = true;
	let message = '';

	const {
		idStatus,
		colorStatus,
		nameStatus,
		values,
		additionalStatus,
	} = req.body.itemDetails;
	const { exchangeId, value } = additionalStatus;

	const orderStatus = await OrderStatus.findOne({ _id: idStatus });

	if (!orderStatus) {
		success = false;
		message = `orderStatus id: ****${idStatus.slice(
			-8
		)} isn't exists in DB`;
	} else {
		orderStatus.colorStatus = colorStatus;
		orderStatus.status = nameStatus;
		orderStatus.values = values;
		if (exchangeId !== '' && value !== '') {
			const newValues = values.map((item, index) => {
				return { exchangeId: item.exchangeId, value: item.value };
			});
			newValues.push({ exchangeId, value });
			orderStatus.values = newValues;
		}

		await orderStatus
			.save()
			.then(() => {
				message = `status ${nameStatus} updated!`;
				success = true;
			})
			.catch((error) => {
				message = `orderStatus id: ****${idStatus.slice(
					-8
				)} isn't updated!`;
				console.log(error);
			});
	}

	const arrOrderStatus = await OrderStatus.find();

	return res.status(200).json({
		success,
		message,
		itemFlag: req.body.itemFlag,
		statuses: getArrayItemsCustomed(arrOrderStatus, 'arrOrderStatus'),
	});
});

// добавление нового P2P-сервиса, payType, currency
reportsRouter.post('/save-item', async (req, res) => {
	let message = '';
	let success = true;
	const { userId, typeItem, objItem } = req.body;

	if (typeItem === 'addNewExchange') {
		const newExchange = {
			name: objItem.fullNameExchange.trim(),
			shortName: objItem.shortNameExchange.trim(),
		};

		// проверка наличия в БД
		const exchange = await Exchange.findOne({
			name: newExchange.name,
		});
		if (exchange) {
			message = `${newExchange.name} exists alredy in DB`;
			console.log(`****${userId.slice(-4)} | ${message}`);
		} else {
			const newItem = new Exchange(newExchange);
			await newItem
				.save()
				.then(() => {
					message = `${newExchange.name} inserted!`;
					console.log(
						`****${userId.slice(-4)} | ${newExchange.name} inserted!`
					);
				})
				.catch((error) => {
					message = `${newExchange.name}: Error inserted`;
					success = false;
					console.log(`****${userId.slice(-4)} | ${error}`);
				});
		}
	} else if (typeItem === 'addNewPayType') {
		const newPayType = {
			payType: objItem.payType,
			iconUrlColor: objItem.iconUrlColor,
		};

		// проверка наличия в БД по названию
		const payType = await PayType.findOne({
			payType: newPayType.payType,
		});
		if (payType) {
			success = false;
			message = `${newPayType.payType} exists alredy in DB`;
			console.log(`****${userId.slice(-4)} | ${message}`);
		} else {
			const newItem = new PayType(newPayType);
			await newItem
				.save()
				.then(() => {
					message = `${newPayType.payType} inserted!`;
					console.log(`****${userId.slice(-4)} | ${message}`);
				})
				.catch((error) => {
					message = `${newPayType.payType}: Error inserted`;
					success = false;
					console.log(`****${userId.slice(-4)} | ${error}`);
				});
		}
	} else if (typeItem === 'addGroupCurrency') {
		const CURRENCY_ICON_URL = '';
		const arr = [];
		const getCurrencyProps = (itemCoin, arr) => {
			const result = [];
			for (let i = 0; i < arr.length; i++) {
				const item = {};
				if (
					arr[i].shortName === 'BN' ||
					arr[i].shortName === 'HB' ||
					arr[i].shortName === 'KX' ||
					arr[i].shortName === 'BZ' ||
					arr[i].shortName === 'GX' ||
					arr[i].shortName === 'BT' ||
					arr[i].shortName === 'PX'
				) {
					item.coinId = arr[i].shortName === 'HB' ? itemCoin.coinIdHB : '';
					item.coinName = '';
					item.exchangeId = arr[i]._id;
					// item.shortName = arr[i].shortName;
					item.switchedOn =
						itemCoin[`${arr[i].shortName}`] === 1 ? true : false;
					result.push(item);
				}
			}
			// console.log(result);
			return result;
		};
		const arrExchanges = await Exchange.find();
		// relocation currency to DB
		for (let i = 0; i < arr.length; i++) {
			const newCurrency = {
				currency: arr[i].asset,
				currencyName: '',
				currencyType: 'coin',
				// symbol: arr[i].symbol,
				iconUrl: arr[i].iconUrl,
				tickerUSDT: arr[i].asset + 'USDT',
				currencyProps: getCurrencyProps(arr[i], arrExchanges),
			};

			// проверка наличия в БД
			const currency = await Currency.findOne({
				currency: newCurrency.currency,
			});
			if (currency) {
				message = `${newCurrency.currency} exists alredy in DB`;
				console.log(`****${userId.slice(-4)} | ${message}`);
			} else {
				// console.log(`${newCurrency.currency} ready to inserting`);
				// console.log(newCurrency);
				const newItem = new Currency(newCurrency);
				await newItem
					.save()
					.then(() => {
						message = `All inserted!`;
						console.log(
							`****${userId.slice(-4)} | ${arr[i].asset} inserted!`
						);
					})
					.catch((error) => {
						message = `Error inserted`;
						success = false;
						console.log(`****${userId.slice(-4)} | ${error}`);
					});
			}
		}
	} else if (typeItem === 'addNewCurrency') {
		const newCurrency = {
			currency: objItem.currency,
			currencyName: objItem.currencyName,
			currencyType: objItem.currencyType,
			symbol: objItem.symbol,
			iconUrl: objItem.iconUrl,
			tickerUSDT: objItem.tickerUSDT,
		};

		// проверка наличия в БД
		const currency = await Currency.findOne({
			currency: newCurrency.currency,
		});
		if (currency) {
			success = false;
			message = `${newCurrency.currency} exists alredy in DB`;
			console.log(`****${userId.slice(-4)} | ${message}`);
		} else {
			const newItem = new Currency(newCurrency);
			await newItem
				.save()
				.then(() => {
					message = `${newCurrency.currency} inserted!`;
					console.log(`****${userId.slice(-4)} | ${message}`);
				})
				.catch((error) => {
					message = `${newCurrency.currency}: Error inserted`;
					success = false;
					console.log(`****${userId.slice(-4)} | ${error}`);
				});
		}
	} else if (typeItem === 'unsetFieldPayMethod') {
		console.log(typeItem);
		// await PayType.updateMany({}, { $unset: { KX: 1 } }, { multi: true });
	} else if (typeItem === 'addGroupOrderStatus') {
		console.log(typeItem);
		const arr = [];
		const getArrValues = (arrValues) => {
			const result = arrValues.map((item, index) => {
				return {
					exchangeId: item.exId,
					value: item.value,
				};
			});
			return result;
		};

		for (let i = 0; i < arr.length; i++) {
			const newItem = {
				status: arr[i].status,
				colorStatus: arr[i].colorStatus,
				values: getArrValues(arr[i].values),
			};
			// console.log(newItem);

			const status = new OrderStatus(newItem);
			await status
				.save()
				.then(() => {
					message = `All inserted!`;
					console.log(
						`****${userId.slice(-4)} | ${arr[i].status} inserted!`
					);
				})
				.catch((error) => {
					message = `Error inserted`;
					success = false;
					console.log(`****${userId.slice(-4)} | ${error}`);
				});
		}
	} else if (typeItem === 'addGroupPayMethod') {
		const PAY_ICON_URL = '';
		const payArr = [];
		const getPayTypeProps = (itemPayType, arr) => {
			const result = [];
			for (let i = 0; i < arr.length; i++) {
				const item = {};
				if (arr[i].shortName === 'BN') {
					item.payId = itemPayType.BN.payId;
					item.payName = itemPayType.BN.payName;
					item.exchangeId = arr[i]._id;
					// item.shortName = arr[i].shortName;
					item.switchedOn =
						item.payId === '' && item.payName === '' ? false : true;
				} else if (arr[i].shortName === 'HB') {
					item.payId = itemPayType.HB.payId;
					item.payName = itemPayType.HB.payName;
					item.exchangeId = arr[i]._id;
					item.shortName = arr[i].shortName;
					item.switchedOn =
						item.payId === '' && item.payName === '' ? false : true;
				} else if (arr[i].shortName === 'KX') {
					item.payId = itemPayType.KX.payId;
					item.payName = itemPayType.KX.payName;
					item.exchangeId = arr[i]._id;
					item.shortName = arr[i].shortName;
					item.switchedOn =
						item.payId === '' && item.payName === '' ? false : true;
				} else if (arr[i].shortName === 'BZ') {
					item.payId = itemPayType.BZ.payId;
					item.payName = itemPayType.BZ.payName;
					item.exchangeId = arr[i]._id;
					item.shortName = arr[i].shortName;
					item.switchedOn =
						item.payId === '' && item.payName === '' ? false : true;
				} else if (arr[i].shortName === 'GX') {
					item.payId = itemPayType.GX.payId;
					item.payName = itemPayType.GX.payName;
					item.exchangeId = arr[i]._id;
					item.shortName = arr[i].shortName;
					item.switchedOn =
						item.payId === '' && item.payName === '' ? false : true;
				} else if (arr[i].shortName === 'BT') {
					item.payId = itemPayType.BT.payId;
					item.payName = itemPayType.BT.payName;
					item.exchangeId = arr[i]._id;
					item.shortName = arr[i].shortName;
					item.switchedOn =
						item.payId === '' && item.payName === '' ? false : true;
				} else if (arr[i].shortName === 'PX') {
					item.payId = itemPayType.PX.payId;
					item.payName = itemPayType.PX.payName;
					item.exchangeId = arr[i]._id;
					item.shortName = arr[i].shortName;
					item.switchedOn =
						item.payId === '' && item.payName === '' ? false : true;
				}
				if (Object.keys(item).length !== 0) result.push(item);
			}
			// console.log(result);
			return result;
		};
		const arrExchanges = await Exchange.find();
		const arr = await PayType.find();
		// console.log(arr.length);
		// relocation currency to DB
		for (let i = 0; i < arr.length; i++) {
			const payMethod = await PayType.findOne({ _id: arr[i]._id });

			if (!payMethod) {
				success = false;
				message = `payMethod id: ****${id.slice(-8)} isn't exists in DB`;
				console.log(message);
			} else {
				payMethod.payTypeProps = getPayTypeProps(arr[i], arrExchanges);

				await payMethod
					.save()
					.then(() => {
						message = `${payMethod.payType} updated!`;
						success = true;
						console.log(message);
					})
					.catch((error) => {
						message = `payMethod id: ****${id.slice(-8)} isn't updated!`;
						console.log(error);
					});
			}
		}
	}

	const arrPayTypes = await PayType.find();
	const arrCurrencies = await Currency.find();
	const arrExchanges = await Exchange.find();

	return res.status(200).json({
		success,
		message,
		payTypes: getArrayItemsCustomed(arrPayTypes, 'arrPayTypes'),
		exchanges: getArrayItemsCustomed(arrExchanges, 'arrExchanges'),
		currencies: getArrayItemsCustomed(arrCurrencies, 'arrCurrencies'),
	});
});

// сохранение balances в БД
reportsRouter.post('/save-balances', async (req, res) => {
	// поиск balance в БД
	const qwery = {
		userId: req.body.userId,
		localDate: req.body.localDate,
	};
	const result = await Balance.find(qwery);

	// если balance не уникальный и нашелся в БД
	if (result.length !== 0) {
		return res.status(200).send({
			success: false,
			message: `****${req.body.userId.slice(
				-4
			)} | This Balance exists in DB`,
		});
	}
	// если balance нет в БД
	else {
		const user = await User.findOne({ _id: req.body.userId });
		const params = {
			exhange: 'Rapira',
			ticker: 'USDTRUB',
			apiKeys: getSingleUserProperty(
				'apiKeys',
				"6813988c4e45542844ad003e", // "Rapira"
				user.properties
			),
		}
		const courseUSDTRUB = await getPriceTicker(params)
		const newBalance = {
			userId: req.body.userId,
			localDate: req.body.localDate,
			cashBalanceRUB: req.body.cashBalanceRUB.toString(), // текущая наличка
			creditBalanceRUB: req.body.creditBalanceRUB.toString(), // текущие кредитки
			// trezorBalanceUSDT: req.body.trezorBalanceUSDT.toString(), // trezor остатки
			balances: req.body.balances,
			// текущий курс USDTRUB
			courseUSDTRUB: courseUSDTRUB.priceTicker,
			// полученные займы
			creditPlusRUB: {
				summ: req.body.creditAcceptedRUB.toString(),
				remark: '',
			},
			// возвращенные займы
			creditMinusRUB: {
				summ: req.body.creditReturnedRUB.toString(),
				remark: '',
			},
		};

		const balance = new Balance(newBalance);
		balance
			.save()
			.then(() => {
				return res.status(200).json({
					success: true,
					message: `****${req.body.userId.slice(
						-4
					)} | This Balance updated!`,
				});
			})
			.catch((error) => {
				console.log(error);
				return res.status(400).json({
					success: false,
					message: `****${req.body.userId.slice(
						-4
					)} | This Balance not updated!`,
				});
			});
	}
});

// групповое получение otc-orders
reportsRouter.post('/all-otc-orders', async (req, res) => {
	const allOrders = await startHandlerAllOtcOrders({
		userId: req.body.userId,
		isInsertOrders: true,
		typeOrder: 'MERCHANT',
	});

	return res.status(200).json({
		success: true,
		message: `Orders from ${allOrders.length} Exchanges getted`,
		orders: allOrders,
	});
});

// групповое получение active-spot-orders
reportsRouter.post('/all-active-spot-orders', async (req, res) => {
	const allOrders = await startHandlerAllSpotOrders({
		userId: req.body.userId,
		isInsertOrders: false,
		typeOrder: 'SPOT',
	});

	return res.status(200).json({
		success: true,
		message: `Orders from ${allOrders.length} Exchanges getted`,
		orders: allOrders,
	});
});

// групповое получение history-spot-orders
reportsRouter.post('/all-history-spot-orders', async (req, res) => {
	const allOrders = await startHandlerAllSpotOrders({
		userId: req.body.userId,
		isInsertOrders: true,
		typeOrder: 'SPOT',
	});

	return res.status(200).json({
		success: true,
		message: `Orders from ${allOrders.length} Exchanges getted`,
		orders: allOrders,
	});
});

// групповое получение balances
reportsRouter.post('/all-balances', async (req, res) => {
	const user = await User.findOne({ _id: req.body.userId });
	const allBalances = user ? await getAllBalances({ user }) : [];
	// console.log(allBalances)
	return res.status(200).json({
		success: allBalances.length !== 0 ? true : false,
		message: `Balances from ${allBalances.length} Exchanges getted`,
		balances: allBalances,
		tickers: await Ticker.find(),
	});
});

//
reportsRouter.post('/all-advs', async (req, res) => {
	return res.status(200).json({
		success: true,
		message: 'This route is in process...',
	});
});
